VUE+Flask登录的初探

您所在的位置:网站首页 vue flask项目 VUE+Flask登录的初探

VUE+Flask登录的初探

2023-11-11 13:11| 来源: 网络整理| 查看: 265

0.前端部分依然基于VueCLI (https://cli.vuejs.org/zh/)

1.创建hello-login文件夹,然后再此文件夹内执行 vue create front-end ,一顿狂回车后,如下图所示:

 

 

 2.安装elementUI,axios,js-cookie,qs  2.1  npm i element-ui -S  (https://element.eleme.cn/#/zh-CN/component/installation)  2.2  npm install --save axios vue-axios  (http://www.axios-js.com/zh-cn/docs/vue-axios.html)  2.3  npm install js-cookie --save (https://www.npmjs.com/package/js-cookie)  2.4  npm install qs --save (https://www.npmjs.com/package/qs)

3.打开main.js,把elementUI和axios加载。搞定这块代码,npm run serve,试试能否正常把项目跑起来。(这是一种编码方式,安装组件算是破坏性的动作,需要勤于测试。以免后期跪了)

import Vue from 'vue' import App from './App.vue' import ElementUI from 'element-ui' import 'element-ui/lib/theme-chalk/index.css' import axios from 'axios' import VueAxios from 'vue-axios' //Vue.config.productionTip = false axios.defaults.withCredentials = true Vue.use(VueAxios,axios) Vue.use(ElementUI) new Vue({ render: h => h(App), }).$mount('#app') View Code

4.在components目录下 创建Login.vue文件

{{ titleMsg }} 提交 重置 export default { name: 'loginForm', data() { return { titleMsg: '欢迎来到旗帜世界', loginData: { username: '', password: '' } } }, methods: { submitForm(formName) { this.$refs[formName].validate((valid) => { if (valid) { console.log('submit') } else { console.log('illegad submit!!'); return false; } }) }, resetForm(formName) { this.$refs[formName].resetFields() console.log('reset') } } } View Code

5.打开App.vue,将helloworld相关代码注释,改写成Login。这种操作可以加深理解vue的组件机制。为后期学习使用router打基础

span"/spanspanVue // import HelloWorld from './components/HelloWorld.vue' import Login from './components/Login.vue' export default { name: 'App', components: { //HelloWorld Login } } #app { font-family: Avenir, Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-align: center; color: #2c3e50; margin-top: 60px; } View Code

6.npm run serve 跑起来后如下图。

 

7.接下来,使用axios把此表单提交到py搭建的后台并返回消息。先转到py端,把后端代码实现一部分。在完成这个功能吧。

--------------------------------------------------------------------------------------------------------------------------------------------------------------

0.后端实现,使用flask(https://dormousehole.readthedocs.io/en/latest/)

1.在hello-login文件夹下创建 back-end文件夹,并运行命令行 py -m venv venv  这时就会在当前目录下创建venv虚拟机 (https://dormousehole.readthedocs.io/en/latest/installation.html#id4)

2.执行venv\scripts\activate 这样就启动了虚拟机环境 

3.开始安装flask, flask-login, flask-cors, jwt 。注意都要在venv虚拟机环境下安装  3.1 pip install Flask (https://dormousehole.readthedocs.io/en/latest/installation.html#flask)  3.2 pip install flask-login  (https://flask-login.readthedocs.io/en/latest/)  3.3 pip install pyjwt  (https://pypi.org/project/PyJWT/)  3.4 pip install -U flask-cors  (https://flask-cors.readthedocs.io/en/latest/)

4.在当前目录下创建app.py文件 敲入代码:

from flask import Flask import json app = Flask(__name__) app.secret_key =b'\x15f\x07\xd3\xd9\xbf*\x82\xd1\xe6\xb4\xf2\x95\xdd\x8f\x12' #命令行中运行后拷贝出随机值 python -c "import os; print(os.urandom(16))" @app.route('/hello') def helloworld(): returnData = {'code': 0, 'msg': 'success', 'data': 'hello world' } return json.dumps(returnData),200 if __name__ == '__main__': app.run(debug = True) View Code

5.在venv虚拟机下 运行py app.py 然后再浏览器中查看 http://localhost:5000/hello  。这说明基本框架已经构建成功。之所以返回如下格式,是参考了这篇博文(https://sobird.me/http-json-api-guide.htm),原始出处并未找到,

6.创建用户单元.user.py。实现了flask_login (https://flask-login.readthedocs.io/en/latest/index.html#your-user-class)所提及的功能。以及用USERS字典暂时代替未来的数据库表。

from flask_login import UserMixin from werkzeug.security import check_password_hash,generate_password_hash USERS = [ { "id":1, "name":"admin", "password":generate_password_hash('123') }, { "id":2, "name":"李四", "password":generate_password_hash('123') }, ] class User(UserMixin): def __init__(self,user): self.username = user.get("name") self.password_hash = user.get("password") self.id = user.get("id") @staticmethod def queryUser(username): for user in USERS: if (user.get('name') == username) : return User(user) return None def verifyPassword(self,password): if self.password_hash is None: return False return check_password_hash(self.password_hash,password) def get_id(self): return self.id def get(user_id): if not user_id: return None for user in USERS: if str(user.get('id')) == str(user_id) : return User(user) print('None') return None View Code

7.创建jwt操作单元jwt_token.py 。实现了对jwt的简单二次封装。其实不做封装也可以  7.1 JWT中 “Registered claims” 包含 iss(发行者),exp(到期时间),sub(主题),aud(受众)是官方建议携带的。我偷懒只采用了到期时间这一个声明。  7.2 jwt可以参考官网(https://jwt.io/)介于国内强大的长城。此官网偶发型能打开。   亦可参考此博文 https://www.cnblogs.com/mantoudev/p/8994341.html

from jwt import jwt,PyJWTError from datetime import datetime,timedelta SECRECT_KEY = b'\x92R!\x8e\xc6\x9c\xb3\x89#\xa6\x0c\xcb\xf6\xcb\xd7\xbc' def genToken(data): expInt = datetime.utcnow() + timedelta(seconds=3) payload = { 'exp': expInt, 'data': data } token = jwt.encode(payload,key= SECRECT_KEY,algorithm= 'HS256') return bytes.decode(token) def verfiyToken(tokenStr): try: tokenBytes = tokenStr.encode('utf-8') payload = jwt.decode(tokenBytes,key= SECRECT_KEY,algorithm= 'HS256') return payload except PyJWTError as e: print("jwt验证失败: %s" % e) return None View Code

8.创建登录逻辑单元 login.py 。同前端的主要交互逻辑都在此处。flask_login的具体实现(https://flask-login.readthedocs.io/en/latest/index.html#installation)

import time import json from flask import Blueprint,request from flask_login import LoginManager,login_user,logout_user,login_required,current_user from user import User,USERS from jwt_token import genToken,verfiyToken login_page = Blueprint('login_page',__name__) login_manager = LoginManager() login_manager.login_view = 'helloworld' @login_page.record_once def on_load(state): login_manager.init_app(state.app) # @login_manager.user_loader # def load_user(user_id): # return User.get(user_id) @login_manager.request_loader def load_user_from_request(request): token = request.headers.get('Authorization') if token == None: return None payload = verfiyToken(token) if payload != None: user = User.queryUser(payload['data']['username']) else: user = None return user @login_page.route('/first') @login_required def firstPage(): returnData = {'code': 0, 'msg': 'success', 'data': 'First Blood(来自' + current_user.username +')' } return returnData,200 @login_page.route('/login', methods=['POST']) def login(): if requesthod == 'POST': username = request.form['username'] password = request.form['password'] user = User.queryUser(username) if (user != None) and (user.verifyPassword(password)) : login_user(user) token = genToken({'username':username,'password':'******'}) returnData = {'code': 0, 'msg': 'success', 'data': {'token':token} } return json.dumps(returnData),200 else : returnData = {'code': 1, 'msg': 'success', 'data': 'username or password is not correct' } return json.dumps(returnData),200 @login_page.route('/logout') @login_required def logout(): username = current_user.username logout_user() returnData = {'code': 0, 'msg': 'success', 'data': ' Bye ' + username } return json.dumps(returnData),200 View Code

9.执行py app.py 后,在postman 分别测试如下链接(注意图中红框内容。):  9.1 http://127.0.0.1:5000/hello  9.2 http://127.0.0.1:5000/login  9.3 http://127.0.0.1:5000/first  9.4 http://127.0.0.1:5000/logout 

 

 

 

 

 

 

 

 10.后端代码初步结束。下一阶段,连接前后端

--------------------------------------------------------------------------------------------------------------------------------------------------

1.打开front-end项目,用axios把后端接口调用起来2.在项目src目录下 创建文件夹 utils 然后在其内创建文件request.js。这里对axios做了简单封装。

import axios from 'axios' import Cookies from 'js-cookie' /****** 创建axios实例 ******/ const service = axios.create({ baseURL: 'http://localhost:5000', // api的base_url timeout: 5000 // 请求超时时间 }) service.interceptors.request.use( config => { config.headers['Authorization'] = Cookies.get('Authorization') return config }, error => { console.log(error) return Promise.reject(error) } ) /****** respone拦截器==>对响应做处理 ******/ // service.interceptors.response.use( // response => { // console.log(response) // //这里根据后端提供的数据进行对应的处理 // if (response.data.result === 'TRUE') { // return response.data; // } // }, // error => { // console.log(error); // return Promise.reject(error) // } // ) export default service; request.js {{ titleMsg }} 提交 重置 测试 登出 import qs from 'qs' import service from '../utils/request' import Cookies from 'js-cookie' export default { name: 'loginForm', data() { return { titleMsg: '欢迎来到旗帜世界', loginData: { username: '', password: '' } } }, methods: { loginForm(formName) { this.$refs[formName].validate((valid) => { if (valid) { service({url: '/login',method: 'post',data: qs.stringify(this.loginData)}) .then(response => { const { data } = response Cookies.set('Authorization',data.data.token) alert('submit!!!' +'\n'+ data.msg) }) .catch(error => { console.log(error) }) } else { console.log('illegad submit!!'); return false; } }) }, testForm() { service({url: '/first',method: 'get'}) .then(response => { const { data } = response alert('firstPage!!!' +'\n'+ data.data) }) .catch(error => { console.log(error) }) }, logoutForm() { service({url: '/logout',method: 'get'}) .then(response => { const { data } = response alert('logout!!!' +'\n'+ data.data) }) .catch(error => { console.log(error) }) } } } Login.vue

3.npm run serve 后,测试。四个按钮

 

 4.其中关注一个状况,当登出后,再次点击测试。测试依然返回成功。这就出现一个问题,登出功能无效,回看后端代码logout是正常运作。稍加分析,即可得出产生这种情况的原因是jwt Token本身的弊端。前文的连接中已经提醒。如何解决此状况,日后再分析

5.收工了。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3